package com.hyts.classcode.enhance.bytebuddy.agent;

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.NamedElement;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.SuperMethodCall;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.utility.JavaModule;

/**
 * project-name:coffice-agent
 * package-name:com.hyts.agent.base.api
 * author:Libo/Alex
 * create-date:2019-02-15 10:17
 * copyright:libo-hyts-github
 * email:libo2dev@aliyun.com
 * description:此类主要用于: 用于处理AgentBuilder.Transformer的相关实现功能
 */
public abstract class ClassAgentTransformer implements AgentBuilder.Transformer {


    /**
     * 操作类名称
     * @return
     */
    public abstract ElementMatcher<? super NamedElement> classNameMatcher();

    /**
     * 方法匹配器
     * @return
     */
    public abstract ElementMatcher<? super MethodDescription> methodMatcher();

    /**W
     * 获取Interceptor拦截器
     * @return
     */
    public abstract Object getInterceptor();

    /**
     * 构造器匹配
     * @return
     */
    public abstract ElementMatcher<? super MethodDescription> constructorMatcher();

    /**
     * @param builder
     * @param typeDescription
     * @param classLoader
     * @param module
     * @return
     */
    @Override
    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) {
        ElementMatcher<? super MethodDescription> methodMatcher = methodMatcher();
        ElementMatcher<? super MethodDescription> constructorMacher =constructorMatcher();
        DynamicType.Builder.MethodDefinition.ImplementationDefinition definition= null;
        if(methodMatcher != null){
            definition = builder.method(methodMatcher);
        }else if(constructorMacher != null){
            definition = builder.constructor(constructorMacher);
        }else{
            definition = builder.method(ElementMatchers.any());
        }
        ElementMatchers.named("");
        return definition.intercept(MethodDelegation.to(getInterceptor()).
                        andThen(SuperMethodCall.INSTANCE));
    }
}
